﻿<Window x:Name="_root"
    x:Class="Kent.Boogaart.Converters.Examples.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Kent.Boogaart.Converters.Examples"
    xmlns:con="http://schemas.kent.boogaart.com/converters"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:sys2="clr-namespace:System;assembly=system"
    Title="WPF Converter Examples"
    WindowState="Maximized">
    <TabControl>
        <TabItem Header="BooleanToVisibilityConverter">
            <StackPanel>
                <Expander Header="Example 1" IsExpanded="True">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a BooleanToVisibilityConverter to automatically collapse the TextBox when the CheckBox is unchecked.
                        </TextBlock>
                        <CheckBox x:Name="checkBox1" IsChecked="True">Uncheck to collapse the text box</CheckBox>
                        <TextBox Visibility="{Binding IsChecked, ElementName=checkBox1, Converter={con:BooleanToVisibilityConverter}}"/>
                        <Label>This label sits below the text box.</Label>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 2">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a BooleanToVisibilityConverter to automatically hide the TextBox when the CheckBox is unchecked.
                        </TextBlock>
                        <CheckBox x:Name="checkBox2" IsChecked="True">Uncheck to hide the text box</CheckBox>
                        <TextBox Visibility="{Binding IsChecked, ElementName=checkBox2, Converter={con:BooleanToVisibilityConverter UseHidden=True}}"/>
                        <Label>This label sits below the text box.</Label>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 3">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a BooleanToVisibilityConverter to automatically collapse the TextBox when the CheckBox is checked.
                        </TextBlock>
                        <CheckBox x:Name="checkBox3">Check to collapse the text box</CheckBox>
                        <TextBox Visibility="{Binding IsChecked, ElementName=checkBox3, Converter={con:BooleanToVisibilityConverter IsReversed=True}}"/>
                        <Label>This label sits below the text box.</Label>
                    </StackPanel>
                </Expander>
            </StackPanel>
        </TabItem>
        
        <TabItem Header="CaseConverter">
            <StackPanel>
                <Expander Header="Example 1" IsExpanded="True">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a CaseConverter to automatically convert any text you enter in the TextBox to lowercase and uppercase.
                        </TextBlock>
                        <TextBox x:Name="_textBox1" Text="Enter some text here."/>
                        <Label Content="{Binding Text, ElementName=_textBox1, Converter={con:CaseConverter Upper}}"/>
                        <Label Content="{Binding Text, ElementName=_textBox1, Converter={con:CaseConverter Lower}}"/>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 2">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a CaseConverter to ensure entered text is always in lowercase, but the backing property is always in uppercase.
                        </TextBlock>
                        <TextBox x:Name="textBox2" Text="{Binding Text, ElementName=textBlock2, Converter={con:CaseConverter SourceCasing=Upper, TargetCasing=Lower}, UpdateSourceTrigger=PropertyChanged}"/>
                        <TextBlock x:Name="textBlock2" Text="This is the backing property."/>
                    </StackPanel>
                </Expander>
            </StackPanel>
        </TabItem>
        
        <TabItem Header="ConverterGroup">
            <StackPanel>
                <Expander Header="Example 1" IsExpanded="True">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a ConverterGroup to first convert the entered to uppercase and then to format it.
                        </TextBlock>
                        <TextBox x:Name="_textBox5" Text="Enter some text here"/>
                        <Label>
                            <Label.Content>
                                <Binding Path="Text" ElementName="_textBox5">
                                    <Binding.Converter>
                                        <con:ConverterGroup>
                                            <con:CaseConverter Casing="Upper"/>
                                            <con:FormatConverter FormatString="Converted to uppercase, that text is '{0}'."/>
                                        </con:ConverterGroup>
                                    </Binding.Converter>
                                </Binding>
                            </Label.Content>
                        </Label>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 2">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a ConverterGroup to use the entered text to either check or uncheck the CheckBox.
                            Try entering "Yes" or "No" - case insensitive.
                        </TextBlock>
                        <TextBox x:Name="_textBox6"/>
                        <CheckBox IsThreeState="True">
                            <CheckBox.IsChecked>
                                <Binding Path="Text" ElementName="_textBox6" FallbackValue="{x:Null}">
                                    <Binding.Converter>
                                        <con:ConverterGroup>
                                            <con:CaseConverter Casing="Upper"/>
                                            <con:MapConverter>
                                                <con:Mapping From="YES">
                                                    <con:Mapping.To>
                                                        <sys:Boolean>True</sys:Boolean>
                                                    </con:Mapping.To>
                                                </con:Mapping>
                                                <con:Mapping From="NO">
                                                    <con:Mapping.To>
                                                        <sys:Boolean>False</sys:Boolean>
                                                    </con:Mapping.To>
                                                </con:Mapping>
                                            </con:MapConverter>
                                        </con:ConverterGroup>
                                    </Binding.Converter>
                                </Binding>
                            </CheckBox.IsChecked>
                        </CheckBox>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 3">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example first converts the entered text to a DateTime and then adds 10 minutes to it. Finally,
                            the result is formatted with a FormatConverter.
                        </TextBlock>
                        <TextBox x:Name="_textBox7"/>
                        <Label>
                            <Label.Content>
                                <Binding Path="Text" ElementName="_textBox7">
                                    <Binding.Converter>
                                        <con:ConverterGroup>
                                            <con:TypeConverter TargetType="{x:Type sys:DateTime}"/>
                                            <con:DateTimeConverter TargetAdjustment="0:10"/>
                                            <con:FormatConverter FormatString="Adding 10 minutes to that we get a time of '{0:t}'."/>
                                        </con:ConverterGroup>
                                    </Binding.Converter>
                                </Binding>
                            </Label.Content>
                        </Label>
                    </StackPanel>
                </Expander>
            </StackPanel>
        </TabItem>
        
        <TabItem Header="DateTimeConverter">
            <StackPanel>
                <Expander Header="Example 1" IsExpanded="True">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a DateTimeConverter to convert a DateTime from UTC format to local time. Click the
                            Button to update the UTC DateTime. NOTE: if you live in a GMT+0 timezone, this example will do
                            nothing (and nor should it).
                        </TextBlock>
                        <Button Click="updateDateTime_Click">Update the UTC DateTime</Button>
                        <StackPanel Orientation="Horizontal">
                            <Label>Without conversion:</Label>
                            <Label Content="{Binding DateTimeUtc, ElementName=_root}"/>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <Label>With conversion:</Label>
                            <Label Content="{Binding DateTimeUtc, ElementName=_root, Converter={con:DateTimeConverter TargetKind=Local}}"/>
                        </StackPanel>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 2">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a DateTimeConverter to add 3 minutes onto a DateTime value.
                        </TextBlock>
                        <Button Click="updateDateTime_Click">Update the DateTime</Button>
                        <StackPanel Orientation="Horizontal">
                            <Label>Without conversion:</Label>
                            <Label Content="{Binding DateTimeUtc, ElementName=_root, Converter={con:DateTimeConverter TargetKind=Local}}"/>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <Label>With conversion:</Label>
                            <Label Content="{Binding DateTimeUtc, ElementName=_root, Converter={con:DateTimeConverter TargetKind=Local, TargetAdjustment=0:3}}"/>
                        </StackPanel>
                    </StackPanel>
                </Expander>
            </StackPanel>
        </TabItem>
        
        <TabItem Header="ExpressionConverter">
            <StackPanel>
                <Expander Header="Example 1" IsExpanded="True">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses an ExpressionConverter to ensure that the blue rectangle is always double the value
                            of the Slider's value. The red rectangle's width is always exactly equal to the Slider's value.
                        </TextBlock>
                        <Slider x:Name="_slider1" Minimum="1" Maximum="{Binding ActualWidth, ElementName=_slider1, Converter={con:ExpressionConverter {}{0} / 2}}"/>
                        <Canvas Height="120">
                            <Rectangle Fill="Red" Height="50" Width="{Binding Value, ElementName=_slider1}"/>
                            <Rectangle Canvas.Top="60" Fill="Blue" Height="50" Width="{Binding Value, ElementName=_slider1, Converter={con:ExpressionConverter {}{0} * 2}}"/>
                        </Canvas>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 2">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses an ExpressionConverter to determine the enabled state of the button. You have to
                            choose the good combination of bands to enable the button.
                        </TextBlock>
                        <CheckBox x:Name="_rammstein">Rammstein</CheckBox>
                        <CheckBox x:Name="_powderfinger">Powderfinger</CheckBox>
                        <CheckBox x:Name="_nickelback">Nickelback</CheckBox>
                        <CheckBox x:Name="_ministry">Ministry</CheckBox>
                        <Button Content="Let me in!">
                            <Button.IsEnabled>
                                <MultiBinding>
                                    <MultiBinding.Converter>
                                        <con:ExpressionConverterExtension>
                                            <con:ExpressionConverterExtension.Expression>
                                                <![CDATA[
                                                {0} && {1} && {3} && !{2}
                                                ]]>
                                            </con:ExpressionConverterExtension.Expression>
                                        </con:ExpressionConverterExtension>
                                    </MultiBinding.Converter>
                                    <Binding Path="IsChecked" ElementName="_rammstein"/>
                                    <Binding Path="IsChecked" ElementName="_powderfinger"/>
                                    <Binding Path="IsChecked" ElementName="_nickelback"/>
                                    <Binding Path="IsChecked" ElementName="_ministry"/>
                                </MultiBinding>
                            </Button.IsEnabled>
                        </Button>
                    </StackPanel>
                </Expander>
            </StackPanel>
        </TabItem>
        
        <TabItem Header="FormatConverter">
            <StackPanel>
                <Expander Header="Example 1" IsExpanded="True">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a FormatConverter to format your name as entered below.
                        </TextBlock>
                        <StackPanel>
                            <Label>Enter your name:</Label>
                            <TextBox x:Name="_textBox2"/>
                        </StackPanel>
                        <Label Content="{Binding Text, ElementName=_textBox2, Converter={con:FormatConverter {}Hello {0}!}}"/>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 2">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a FormatConverter to format both your name and the current time.
                        </TextBlock>
                        <StackPanel>
                            <Label>Enter your name:</Label>
                            <TextBox x:Name="_textBox3"/>
                        </StackPanel>
                        <Button Click="updateDateTime_Click">Update the Time</Button>
                        <Label>
                            <Label.Content>
                                <MultiBinding Converter="{con:FormatConverter {}Hello {0} the time is {1:t}.}">
                                    <Binding Path="Text" ElementName="_textBox3"/>
                                    <Binding Path="DateTimeUtc" ElementName="_root" Converter="{con:DateTimeConverter TargetKind=Local}"/>
                                </MultiBinding>
                            </Label.Content>
                        </Label>
                    </StackPanel>
                </Expander>
            </StackPanel>
        </TabItem>

        <TabItem Header="MapConverter">
            <StackPanel>
                <Expander Header="Example 1" IsExpanded="True">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a MapConverter to convert between Boolean and Visibility. Checking the CheckBox
                            displays a Label; unchecking it hides the Label.
                        </TextBlock>
                        <CheckBox x:Name="_checkBox1">Show Label</CheckBox>
                        <Label Content="Here is the label.">
                            <Label.Visibility>
                                <Binding Path="IsChecked" ElementName="_checkBox1" FallbackValue="Collapsed">
                                    <Binding.Converter>
                                        <con:MapConverter>
                                            <con:Mapping To="{x:Static Visibility.Visible}">
                                                <con:Mapping.From>
                                                    <sys:Boolean>True</sys:Boolean>
                                                </con:Mapping.From>
                                            </con:Mapping>
                                        </con:MapConverter>
                                    </Binding.Converter>
                                </Binding>
                            </Label.Visibility>
                        </Label>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 2">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a MapConverter to convert between the selected UriFormat enumeration member and a
                            human-readable string.
                        </TextBlock>
                        <ComboBox x:Name="_comboBox1"/>
                        <Label>
                            <Label.Content>
                                <Binding Path="SelectedValue" ElementName="_comboBox1">
                                    <Binding.Converter>
                                        <con:MapConverter FallbackBehavior="ReturnOriginalValue">
                                            <con:Mapping From="{x:Static sys2:UriFormat.SafeUnescaped}" To="Unescaped but safe"/>
                                            <con:Mapping From="{x:Static sys2:UriFormat.UriEscaped}" To="Escaped"/>
                                        </con:MapConverter>
                                    </Binding.Converter>
                                </Binding>
                            </Label.Content>
                        </Label>
                    </StackPanel>
                </Expander>
                <Expander Header="Example 3">
                    <StackPanel>
                        <TextBlock Style="{StaticResource ExampleHeader}">
                            This example uses a MapConverter to display a different image depending on whether the CheckBox is
                            checked or not.
                        </TextBlock>
                        <CheckBox x:Name="_checkBox2">Check me</CheckBox>
                        <Image Height="200">
                            <Image.Source>
                                <Binding Path="IsChecked" ElementName="_checkBox2">
                                    <Binding.Converter>
                                        <con:MapConverter>
                                            <con:Mapping To="{StaticResource Tick}">
                                                <con:Mapping.From>
                                                    <sys:Boolean>True</sys:Boolean>
                                                </con:Mapping.From>
                                            </con:Mapping>
                                            <con:Mapping To="{StaticResource Cross}">
                                                <con:Mapping.From>
                                                    <sys:Boolean>False</sys:Boolean>
                                                </con:Mapping.From>
                                            </con:Mapping>
                                        </con:MapConverter>
                                    </Binding.Converter>
                                </Binding>
                            </Image.Source>
                        </Image>
                    </StackPanel>						
                </Expander>
            </StackPanel>
        </TabItem>

        <TabItem Header="MultiConverterGroup">
            <Expander Header="Example 1" IsExpanded="True">
                <StackPanel>
                    <TextBlock Style="{StaticResource ExampleHeader}">
                        This example uses a MultiConverterGroup to pass the entered text through multiple levels of
                        FormatConverters.
                    </TextBlock>
                    <TextBox x:Name="_textBox8"/>
                    <TextBox x:Name="_textBox9"/>
                    <Label>
                        <Label.Content>
                            <MultiBinding>
                                <MultiBinding.Converter>
                                    <con:MultiConverterGroup>
                                        <con:MultiConverterGroupStep>
                                            <con:FormatConverter FormatString="{}{0}, {1}"/>
                                            <con:FormatConverter FormatString="{}{1}, {0}"/>
                                        </con:MultiConverterGroupStep>
                                        <con:MultiConverterGroupStep>
                                            <con:FormatConverter FormatString="{}The set of values you entered could be written as [{0}] or [{1}]."/>
                                        </con:MultiConverterGroupStep>
                                    </con:MultiConverterGroup>
                                </MultiBinding.Converter>
                                <Binding Path="Text" ElementName="_textBox8"/>
                                <Binding Path="Text" ElementName="_textBox9"/>
                            </MultiBinding>
                        </Label.Content>
                    </Label>
                </StackPanel>
            </Expander>
        </TabItem>
        
        <TabItem Header="TypeConverter">
            <Label>Please see the third ConverterGroup example.</Label>
        </TabItem>

        <TabItem Header="Full Example: Identikit">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                
                <TextBlock Grid.ColumnSpan="2" Style="{StaticResource ExampleHeader}">
                    In this example I use a number of the converters to allow the user to construct a simple profile of a
                    perpetrator. The default settings are my particulars which, by law of averages, should end up saving the law
                    some time ;)
                </TextBlock>
                
                <Label Grid.Row="1">Gender:</Label>
                <ComboBox x:Name="_genderComboBox" Grid.Row="1" Grid.Column="1" SelectedIndex="0"/>

                <Label Grid.Row="2">Height:</Label>
                <Slider x:Name="_heightSlider" Grid.Row="2" Grid.Column="1" Minimum="100" Maximum="200" Value="183"/>

                <Label Grid.Row="3">Weight:</Label>
                <Slider x:Name="_weightSlider" Grid.Row="3" Grid.Column="1" Minimum="50" Maximum="150" Value="82"/>

                <Image Grid.Row="4" Grid.ColumnSpan="2" Height="{Binding Value, ElementName=_heightSlider, Converter={con:ExpressionConverter {}{0} * 2}}" Stretch="Fill">
                    <Image.Width>
                        <MultiBinding Converter="{con:ExpressionConverter {}{1} * 2.3 - ({0} / 2)}">
                            <Binding Path="Value" ElementName="_heightSlider"/>
                            <Binding Path="Value" ElementName="_weightSlider"/>
                        </MultiBinding>
                    </Image.Width>
                    <Image.Source>
                        <Binding Path="SelectedItem" ElementName="_genderComboBox">
                            <Binding.Converter>
                                <con:MapConverter>
                                    <con:Mapping From="{x:Static local:Gender.Male}" To="{StaticResource Male}"/>
                                    <con:Mapping From="{x:Static local:Gender.Female}" To="{StaticResource Female}"/>
                                </con:MapConverter>
                            </Binding.Converter>
                        </Binding>
                    </Image.Source>
                </Image>

                <Label Grid.Row="5" Grid.ColumnSpan="2" HorizontalAlignment="Center" FontSize="16">
                    <Label.Content>
                        <MultiBinding Converter="{con:FormatConverter {}Suspect is {0}\, {1:0.0}cm tall and {2:0.0}kg in weight.}">
                            <Binding Path="SelectedItem" ElementName="_genderComboBox">
                                <Binding.Converter>
                                    <con:ConverterGroup>
                                        <con:TypeConverter TargetType="{x:Type sys:String}"/>
                                        <con:CaseConverter Casing="Lower"/>
                                    </con:ConverterGroup>
                                </Binding.Converter>
                            </Binding>
                            <Binding Path="Value" ElementName="_heightSlider"/>
                            <Binding Path="Value" ElementName="_weightSlider"/>
                        </MultiBinding>
                    </Label.Content>
                </Label>
            </Grid>
        </TabItem>
    </TabControl>
</Window>
